﻿using System;
using System.Reflection;
using Phoenix.Xna.Framework.Reflection;

namespace Phoenix.Xna.Framework.Serialization
{
    /// <summary>
    /// Use this attribute to define a field should be persisted only if the current value is not equal to predetermined default value.
    /// </summary>
    [AttributeUsage(AttributeTargets.Field)]
    public sealed class SerializableFieldAttribute : Attribute
    {
        /// <summary>
        /// Gets the default value for a given field.  DefaultValueAttribute.ShouldPersist() compares this value to the value that is currently set.
        /// </summary>
        public object DefaultValue { get; private set; }

        /// <summary>
        /// Initializess a new instance of the SerializableFieldAttribute class.
        /// </summary>
        /// <param name="defaultValue">The default value of the field.</param>
        public SerializableFieldAttribute(object defaultValue)
        {
            DefaultValue = defaultValue;
        }

        /// <summary>
        /// Confirm the field's value is not the default value and therefore should persist.
        /// </summary>
        /// <param name="field">The FieldInfo for the field to serialize.</param>
        /// <param name="instance">The object to containing the field.</param>
        internal static bool ShouldPersist(FieldInfo field, object instance)
        {
            SerializableFieldAttribute defaultValue = field.GetFirstAttributeOfType<SerializableFieldAttribute>(true);

            if (defaultValue != null)
            {
                if ((instance == null && defaultValue.DefaultValue != null) || (instance != null && !instance.Equals(defaultValue.DefaultValue)))
                {
                    return true;
                }
            }

            return false;
        }
    }
}
